package com.zz.framework.widget

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Outline
import android.graphics.Paint
import android.graphics.Path
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
import android.graphics.Rect
import android.graphics.RectF
import android.os.Build
import android.util.AttributeSet
import android.view.View
import android.view.ViewOutlineProvider
import android.widget.LinearLayout
import androidx.annotation.RequiresApi
import androidx.constraintlayout.widget.ConstraintLayout
import com.zz.framework.R

/**
 * Copyright © 2025 zhun All rights reserved.
 * Created by ZhaoZhun on 2025/1/17 13:10.
 * @author: ZhaoZhun 1820022519@qq.com
 * @version: V1.0
 * cornerMode用于选择实现方式，可选实现方式有
 * outline：
 * 支持同时设置四个圆角以及单独设置上圆角或者下圆角，但所有圆角弧度必须相同，不支持单独配置
 * 性能：绘制性能最优，暂未发现兼容和锯齿问题
 * xfermode：
 * 支持四个圆角单独设置和同时设置
 * 性能：性能稍差，同时抗锯齿效果比clippath会好一些
 * clippath：
 * 支持四个圆角单独设置和同时设置，实现最灵活。
 * 性能：性能稍差，同时低版本机型锯齿明显，同时和硬件加速有兼容问题，部分机型存在渲染闪烁了切割黑屏
 * outline的实现方式需要配置 topCornerRadius或者bottomCornerRadius即可
 * xfermode和clippath的实现方式则需要根据上下左右四个圆角分别配置
 */
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
class RoundCornerConstraintLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {
    companion object {
        private const val TAG = "RoundCornerLayout"
        private const val CORNER_MODE_OUTLINE = 0
        private const val CORNER_MODE_XFERMODE = 1
        private const val CORNER_MODE_CLIPPATH = 2
    }

    private var cornerMode = 0
    private var cornerRadius = 0
    private var topCornerRadius = 0
    private var topLeftCornerRadius = 0
    private var topRightCornerRadius = 0
    private var bottomCornerRadius = 0
    private var bottomLeftCornerRadius = 0
    private var bottomRightCornerRadius = 0

    private var mRoundRectPath = Path()
    private var mPaint = Paint()
    private val mRect = RectF()
    private var roundedCorners = FloatArray(8)
    private var maskBitmap: Bitmap? = null

    init {
        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundCornerLayout, defStyleAttr, 0)
        cornerMode =
            typedArray.getInt(
                R.styleable.RoundCornerLayout_cornerMode,
                CORNER_MODE_OUTLINE
            )
        cornerRadius = typedArray.getDimensionPixelSize(R.styleable.RoundCornerLayout_cornerRadius, 0)
        topCornerRadius = typedArray.getDimensionPixelSize(R.styleable.RoundCornerLayout_topCornerRadius, 0)
        topLeftCornerRadius = typedArray.getDimensionPixelSize(R.styleable.RoundCornerLayout_topLeftCornerRadius, 0)
        topRightCornerRadius = typedArray.getDimensionPixelSize(R.styleable.RoundCornerLayout_topRightCornerRadius, 0)
        bottomCornerRadius = typedArray.getDimensionPixelSize(R.styleable.RoundCornerLayout_bottomCornerRadius, 0)
        bottomLeftCornerRadius = typedArray.getDimensionPixelSize(R.styleable.RoundCornerLayout_bottomLeftCornerRadius, 0)
        bottomRightCornerRadius = typedArray.getDimensionPixelSize(R.styleable.RoundCornerLayout_bottomRightCornerRadius, 0)
        if (cornerRadius > 0) {
            topCornerRadius = cornerRadius
            bottomCornerRadius = cornerRadius
        }
        typedArray.recycle()
        mPaint.isAntiAlias = true
        updateRoundRectMode()
    }

    private fun setRoundRectPath() {
        roundedCorners[0] = topLeftCornerRadius.toFloat()
        roundedCorners[1] = topLeftCornerRadius.toFloat()
        roundedCorners[2] = topRightCornerRadius.toFloat()
        roundedCorners[3] = topRightCornerRadius.toFloat()
        roundedCorners[4] = bottomLeftCornerRadius.toFloat()
        roundedCorners[5] = bottomLeftCornerRadius.toFloat()
        roundedCorners[6] = bottomRightCornerRadius.toFloat()
        roundedCorners[7] = bottomRightCornerRadius.toFloat()
        mRect.set(0f, 0f, width.toFloat(), height.toFloat())
        mRoundRectPath.rewind()
        mRoundRectPath.addRoundRect(mRect, roundedCorners, Path.Direction.CW)
    }


    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    private fun setOutlineMode() {//讨巧上下多截出去一点，达到只有上圆角或者下圆角，实际还是一致的圆角
        when {
            topCornerRadius != 0 && bottomCornerRadius == 0 -> {
                clipToOutline = true
                outlineProvider = @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
                object : ViewOutlineProvider() {
                    override fun getOutline(view: View, outline: Outline) {
                        outline.setRoundRect(
                            Rect(0, 0, view.width, view.height + topCornerRadius),
                            topCornerRadius.toFloat()
                        )
                    }
                }
            }

            topCornerRadius == 0 && bottomCornerRadius != 0 -> {
                clipToOutline = true
                outlineProvider = object : ViewOutlineProvider() {
                    override fun getOutline(view: View, outline: Outline) {
                        outline.setRoundRect(
                            Rect(0, 0 - bottomCornerRadius, view.width, view.height),
                            bottomCornerRadius.toFloat()
                        )
                    }
                }
            }

            topCornerRadius != 0 && bottomCornerRadius != 0 && bottomCornerRadius == topCornerRadius -> {
                clipToOutline = true
                outlineProvider = object : ViewOutlineProvider() {
                    override fun getOutline(view: View, outline: Outline) {
                        outline.setRoundRect(
                            Rect(0, 0, view.width, view.height),
                            topCornerRadius.toFloat()
                        )
                    }
                }
            }
        }
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    private fun updateRoundRectMode() {
        when (cornerMode) {
            CORNER_MODE_OUTLINE -> {
                setOutlineMode()
            }

            else -> clipToOutline = false
        }
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        when (cornerMode) {
            CORNER_MODE_XFERMODE -> {
                maskBitmap?.recycle()
                maskBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888).apply {
                    val canvasTmp = Canvas(this)
                    setRoundRectPath()
                    canvasTmp.drawPath(mRoundRectPath, mPaint)
                }
            }

            CORNER_MODE_CLIPPATH -> {
                setRoundRectPath()
            }
        }
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun dispatchDraw(canvas: Canvas) {
        when (cornerMode) {
            CORNER_MODE_CLIPPATH -> {
                canvas?.clipPath(mRoundRectPath) //切割指定区域
                super.dispatchDraw(canvas)
            }

            CORNER_MODE_XFERMODE -> {
                val layerId = canvas?.saveLayer(mRect, mPaint) ?: -1
                super.dispatchDraw(canvas)
                mPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN) //设置图层混合模式
                maskBitmap?.run {
                    canvas?.drawBitmap(this, 0f, 0f, mPaint)
                }
                mPaint.xfermode = null
                canvas?.restoreToCount(layerId)
            }

            else -> {
                super.dispatchDraw(canvas)
            }
        }
    }
}
